/*
 * @(#)BaseClient.java MinaNetSocket 2016年12月16日
 * Copyright (c) 2010-2020 Easy ITS, Inc. All rights reserved.
 */
package zhanglu.family.socket.serialization.client;

import java.net.InetSocketAddress;

import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

/**
 * 实例化客户端端的管理类
 * 
 * @author zhanglu
 * @date 2016年12月16日
 */
public class BaseTCPClient {

    private NioSocketConnector connector;       // 总进程

    private ConnectFuture      connectFuture;   // 客户端连接

    private IoHandlerAdapter   handlerAction;   // 业务处理类

    private int                idleTime = 10;   // 连接超时时间毫秒

    private String             ip;              // 服务端IP

    private int                port;            // 服务端端口

    private int                reconnectionTime; // 客户端重连间隔时间毫秒

    /**
     * 
     * @param handlerAction
     *            业务处理类
     * @param idleTime
     *            连接超时时间毫秒
     * @param ip
     *            服务端IP
     * @param port
     *            服务端端口
     * @param reconnectionTime
     *            客户端重连间隔时间毫秒
     * @param msgType
     *            消息类型，可以为0
     * @param sessionSeq
     *            标示session连接的唯一key，可以为0
     */
    public BaseTCPClient(IoHandlerAdapter handlerAction, int idleTime, String ip, int port, int reconnectionTime) {
        this.handlerAction = handlerAction;
        this.idleTime = idleTime;
        this.ip = ip;
        this.port = port;
        this.reconnectionTime = reconnectionTime;
    }

    /**
     * 启动
     */
    public void startClient() {
        reconnection();
    }

    /**
     * 发送消息
     * 
     * @param msg
     */
    public void sendMsg(Object msg) {
        try {
            if (this.connectFuture != null) {
                this.connectFuture.getSession().write(msg);
            }
        } catch (Exception e) {
            System.out.println("连接错误");
        }
    }

    /**
     * 关闭连接
     */
    public void closeSession() {
        if (this.connectFuture != null && this.connectFuture.getSession() != null) {
            this.connectFuture.getSession().close(true);
        }
    }

    /**
     * 杀掉整个连接的进程
     */
    public void dispose() {
        if (this.connector != null) {
            this.connector.dispose();
            this.connector = null;
            System.out.println("进程已经杀死");
        }
    }

    /**
     * 重连
     * 
     * @param msgType
     *            消息类型
     * @param sessionSeq
     *            连接标示
     */
    @SuppressWarnings("deprecation")
    public void reconnection() {

        if (this.connector == null) {

            this.connector = new NioSocketConnector();
            // 创建接受数据的过滤器
            DefaultIoFilterChainBuilder chain = this.connector.getFilterChain();
            // 设定这个过滤器将一行一行(/r/n)的读取数据
            chain.addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));// 序列化处理

            // 客户端的消息处理器：一个SamplMinaServerHander对象
            this.connector.setHandler(this.handlerAction);
            // set connect timeout
            this.connector.setConnectTimeout(this.idleTime);
        }

        while (this.connectFuture == null || !connectFuture.isConnected()) {
            try {

                this.connectFuture = connector.connect(new InetSocketAddress(this.ip, this.port));
                this.connectFuture.awaitUninterruptibly();
                this.connectFuture.getSession().write("");
                System.out.println("客户端连接成功,服务端ip为" + this.ip + ",服务端端口为" + this.port);

                break;

            } catch (Exception e) {
                try {
                    this.connectFuture = null;
                    System.out.println("客户端连接失败进行重连,服务端ip为" + this.ip + ",服务端端口为" + this.port);
                    Thread.sleep(this.reconnectionTime);
                    continue;
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                    continue;
                }
            }
        }
    }
}
